from  deslab import *

"""
This is the script for the computation of minimal event bases that ensure diagnosability.
The algorithms are part of the paper:
Basilio, J., Lima, S., Lafortune, S.,, e Moreira, M. (2012), "Computation of minimal
event bases that ensure diagnosability," Discrete Event Dynamic Systems, 
"""

from minimal_basis import *
from algorithm1 import find_EDES
from algorithm3 import find_Sigma_IES_Obs
from algorithm4 import find_Sigma_IES_Uobs


def find_minimal_basis(Gd, G, sf):
    # starting
    So = G.Sigobs            
    # Step 1:
    #    Calculating $\Sigma_{EDES}$    
    Sigma_EDES,tree = find_EDES(Gd)    
    # Step 2:
    #    Setting $\Sigma_{mdbc}$, $\Sigma_{EDES}$ and $\Sigma_{mdb}$
    Sigma_mdbc = list(Sigma_EDES) 
    Sigma_mdbc.sort(key=len, reverse=True) # ordering $Sigma_mdbc$ by size.
    Sigma_mdb = set()    
    
    # Step 3
    while Sigma_mdbc:    
        Sop = Sigma_mdbc.pop()                
        Gdp = diagnoser(G,sf,Sop)
        # we detect if $G\prime_d$ has indeterminate cycles
        ind_states = find_indeterminate_states(G, Gdp, sf)        
        if not ind_states:
            # if $G_d$ is diagnosable
            Sigma_mdb |= set([Sop])
        else:
            # if $G\prime_d$ is not diagnosable 
            Gtest = Gdp//Gd
            # next we calculate the set XDS which corresponds with prime paths of  $G\prime_d$
            XDS, tree1 = find_XDS(Gdp) 
            # next we calculate the set XST which corresponds with prime paths in  $G_{test}$
            XST, tree2 = prime_paths_cycle_smax(Gtest)    
            # next we use algorithm 3 for finding  events corresponding to observable cycles             
            Sigmao_ies, S_Y, S_N  = find_Sigma_IES_Obs(XDS, XST, ind_states, So, Sop)
            # next we use algorithm 3 for finding  events corresponding to hidden cycles 
            Sigmah_ies = find_Sigma_IES_Uobs(XST, S_Y, S_N, So, Sop) 
            # we compose the collection of $\Sigma^o_{ies}$ and $\Sigma^o_{ies}$
            SOH = set([Sigmao_ies, Sigmah_ies ])
            #next we calculate the union and the minimal elements of poset
            Sigma_ies = prodcollection(SOH)    
            Sigma_ies = minimals_of_poset(Sigma_ies)  
            # We calculate $\{\Sigma_o\prime \} \times \Sigma_{ies}$                            
            P = prodcollection([set([Sop]), Sigma_ies])     
            U = set(Sigma_mdbc) | P
            # we find the minimal elements of poset $U \cap \Sigma_{mdb}$
            Sigma_mdbc = [bc  for bc in minimals_of_poset(U | Sigma_mdb) if bc not in Sigma_mdb]              
            Sigma_mdbc.sort(key=len, reverse=True) 
            if len(Sigma_mdbc)==1:
                if Sigma_mdbc[0] == So:                    
                    return  set([So])       
    return Sigma_mdb
            
        
     
""" TESTING CODE """

#
sf = syms('f')
G = load('G_example3')
Gd = load('Gd_example3')
B =find_minimal_basis(Gd, G, sf)
print B



      
    
